package recompiled;

/**
 * TARGET PC: 0xA0000040
 */
public class A0000040 extends compiler.BasicBlock {

	private static final A0000040 INSTANCE = new A0000040();

	private A0000040(){}

	/**
	 * @see compiler.BasicBlock#getBasicBlock 
	 */
	public static compiler.BasicBlock getBasicBlock() {
		return INSTANCE;
	}

	/**
	 * {@inheritDoc}
	 */
	@Override
	public void execute() throws mips.exceptions.MipsException {

		//0xa0000040 
		//0x27bdffd8 
		//ADDIU
		u32_gpr_rs = mips.instructions.Instruction.zeroExtendW(mips.CPU.GPR[29]); 
		
		mips.CPU.GPR[29] = (int)((u32_gpr_rs + -40) & 4294967295L);
		
		mips.CPU.PC = mips.CPU.nPC;
		mips.CPU.nPC = mips.CPU.PC + 4;


		//0xa0000044 
		//0xafbf0020 
		//SW
		n64.MemoryManager.writeWord(mips.CPU.GPR[31], mips.CPU.GPR[29] + 32);
		
		mips.CPU.PC = mips.CPU.nPC;
		mips.CPU.nPC = mips.CPU.PC + 4;

		//0xa0000048 
		//0xafbe001c 
		//SW
		n64.MemoryManager.writeWord(mips.CPU.GPR[30], mips.CPU.GPR[29] + 28);
		
		mips.CPU.PC = mips.CPU.nPC;
		mips.CPU.nPC = mips.CPU.PC + 4;

		//0xa000004c 
		//0xafb00018 
		//SW
		n64.MemoryManager.writeWord(mips.CPU.GPR[16], mips.CPU.GPR[29] + 24);
		
		mips.CPU.PC = mips.CPU.nPC;
		mips.CPU.nPC = mips.CPU.PC + 4;

		//0xa0000050 
		//0x03a0f020 
		//ADD
		u32_gpr_rs = mips.instructions.Instruction.zeroExtendW(mips.CPU.GPR[29]);
		u32_gpr_rt = mips.instructions.Instruction.zeroExtendW(mips.CPU.GPR[0]);
		
		if (u32_gpr_rs + u32_gpr_rt > 4294967295L) {
			throw new mips.exceptions.OverflowException(mips.CPU.PC,0x03A0F020);
		} 
		else {
			mips.CPU.GPR[30] = mips.CPU.GPR[29] + mips.CPU.GPR[0];
		}
		
		mips.CPU.PC = mips.CPU.nPC;
		mips.CPU.nPC = mips.CPU.PC + 4;


		//0xa0000054 
		//0xafc40028 
		//SW
		n64.MemoryManager.writeWord(mips.CPU.GPR[4], mips.CPU.GPR[30] + 40);
		
		mips.CPU.PC = mips.CPU.nPC;
		mips.CPU.nPC = mips.CPU.PC + 4;

		//0xa0000058 
		//0x8fc20028 
		//LW
		mips.CPU.GPR[2] = n64.MemoryManager.readWord(mips.CPU.GPR[30] + 40);
		
		mips.CPU.PC = mips.CPU.nPC;
		mips.CPU.nPC = mips.CPU.PC + 4;


		//0xa000005c 
		//0x00000020 
		//NOP
		mips.CPU.PC = mips.CPU.nPC;
		mips.CPU.nPC = mips.CPU.PC + 4;


		//0xa0000060 
		//0x14400004 
		//BNE
		if (mips.CPU.GPR[2] != mips.CPU.GPR[0]) {
			
			mips.CPU.PC = mips.CPU.nPC;
			mips.CPU.nPC = mips.CPU.PC + 16;
		} 
		else {
			
			mips.CPU.PC = mips.CPU.nPC;
			mips.CPU.nPC = mips.CPU.PC + 4;
		}


		if(!skipDelaySlot) {
			//0xa0000064 
			//0x00000020 
			//NOP
			mips.CPU.PC = mips.CPU.nPC;
		mips.CPU.nPC = mips.CPU.PC + 4;

		}
		
	}

	public static int instructionLength = 10;

	/**
	 * {@inheritDoc}
	 */
	@Override
	public int blockLength() {
		int returnLen = instructionLength;
		if(skipDelaySlot) {
			returnLen -= 1;
			skipDelaySlot = false;
		}
		return returnLen;
	}
}

